use axum::{
    Json,
    http::{ Request, HeaderMap },
    response::Response,
    middleware::Next,
    body::Body
};
use serde_json::Value;

use crate::{auth::jwt::{token_decode, Claims}, code};

pub fn has_token(header:HeaderMap) -> bool {
    if let Some(f) = header.get("authorization"){
        if let Ok(d) = f.to_str() {
            !d.to_owned().contains("Undefined")
        }else{
            false
        }
    }else{
        false
    }
}
pub fn get_token(header:HeaderMap) -> Result<String, Json<Value>> {
    if let Some(f) = header.get("authorization") {
        if let Ok(d) = f.to_str() {
            if d.to_owned().contains("Undefined") {
                Err( code::fail_(201) )
            }else{
                Ok( d.to_owned() )
            }
        }else{
            Err( code::fail_(201) )
        }
    }else{
        Err( code::fail_(201) )
    }
}

pub fn get_claims(header:HeaderMap) -> Result<Claims, Json<Value>> { token_decode(Some(&get_token(header)?), false) }
pub fn get_id(header:HeaderMap) -> Result<i32, Json<Value>> { Ok(get_claims(header)?.id) }
pub fn get_user_id(header:HeaderMap) -> Result<u32, Json<Value>> { Ok(get_claims(header)?.id as u32) }
pub fn get_name(header:HeaderMap) -> Result<Option<String>, Json<Value>> { Ok(get_claims(header)?.name) }

pub fn get_role_op(header:HeaderMap) -> Result<Option<i8>, Json<Value>> { Ok(get_claims(header)?.role) }
pub fn get_role(header:HeaderMap) -> Result<i8, Json<Value>> {
    if let Some(f) = get_claims(header)?.role {
        Ok(f)
    }else{
        Err(code::sys_("角色 role 不存在"))
    }
}
pub fn get_roles(header:HeaderMap) -> Result<Vec<i32>, Json<Value>> { Ok(get_claims(header)?.roles.unwrap_or_default()) }
pub fn get_uuid(header:HeaderMap) -> Result<String, Json<Value>> { Ok(get_claims(header)?.uuid) }
pub fn get_username(header:HeaderMap) -> Result<String, Json<Value>> { Ok(get_claims(header)?.username) }

pub async fn get_req_claims<T:Fn(Claims)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, is_exp:bool, callback:T) -> Result<Response, Json<Value>> {
    let mut err = false;
    if let Some(f) = req.headers().get(http::header::AUTHORIZATION){
        if let Ok(d) = f.to_str() {
            if d.to_owned().contains("Undefined") {
                err = true;
            }else{
                let claims = token_decode(Some(d), is_exp)?;
                callback(claims)?;
            }
        }else{
            err = true;
        }
    }else {
        err = true;
    }
    if err {
        Err( code::fail_(201) )
    }else{
        Ok(next.run(req).await)
    }
}
pub async fn get_req_role_op<T:Fn(Option<i8>)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, callback:T) -> Result<Response, Json<Value>> {
    get_req_claims(req, next, false,|d| callback(d.role)).await
}
pub async fn get_req_role<T:Fn(i8)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, callback:T) -> Result<Response, Json<Value>> {
    get_req_claims(req, next, false,|d| {
        if let Some(f) = d.role{
            callback(f)
        }else {
            Err(code::sys_("角色 role 不存在"))
        }
    }).await
}
pub async fn get_req_roles<T:Fn(Option<i8>, Option<Vec<i32>>)->Result<(),Json<Value>>>(req: Request<Body>, next: Next, callback:T) -> Result<Response, Json<Value>> {
    get_req_claims(req, next, false,|d| callback(d.role, d.roles)).await
}